Redux 是一個在 React 應用程式中常用的狀態管理工具,能夠有效地管理大型應用中的全域狀態。當我們使用 TypeScript 與 Redux 時,型別支持能幫助我們避免常見的錯誤,並提供更好的開發體驗。在今天的文章中,將介紹如何為 action
和 reducer
定義型別,做到更加健壯 Redux 程式碼的效果。
在 Redux 中,action
是一個 JavaScript 物件,描述了希望發生的事情(如更新狀態)。而 reducer
則是一個函式,根據接收到的 action 來更新狀態。
舉個例子,如果我們有一個簡單的計數器應用,當我們點擊按鈕時,計數器的當前值會增加或減少。這些「增加」和「減少」的行為就是我們的 action
,而更新狀態的邏輯就是 reducer
。
我們通常會根據應用的不同需求定義多個 action
,而使用 TypeScript,可以為每個 action
定義型別。
假我們有兩個 action
:一個是 INCREMENT
用來增加計數、另一個是 DECREMENT
用來減少計數。
// 定義 Action 的字面量型別
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
// 定義 Action 物件的型別
interface IncrementAction {
type: typeof INCREMENT;
}
interface DecrementAction {
type: typeof DECREMENT;
}
// 使用聯合型別定義可能的所有 Action
export type CounterActionTypes = IncrementAction | DecrementAction;
為了方便使用,通常會建立「Action 創建函式」來生成 action
物件。這樣可以讓程式碼更易於維護且確保型別正確。
// Action 創建函式
export const increment = (): IncrementAction => ({
type: INCREMENT,
});
export const decrement = (): DecrementAction => ({
type: DECREMENT,
});
reducer
是負責根據 action 來更新應用狀態的函式。在 Redux 中,reducer
會根據當前的狀態以及接收到的 action
來決定如何更新狀態。
首先是定義狀態的型別:
// 定義計數器的狀態型別
export interface CounterState {
count: number;
}
接下來,則是定義 reducer
,來處理不同的 action
並更新狀態。先將 action
的型別指定為 CounterActionTypes
,這樣 TypeScript 可以協助檢查每個 action
是否符合預期。
// 初始狀態
const initialState: CounterState = {
count: 0,
};
// 定義 reducer
export const counterReducer = (
state: CounterState = initialState,
action: CounterActionTypes
): CounterState => {
switch (action.type) {
case INCREMENT:
return {
...state,
count: state.count + 1,
};
case DECREMENT:
return {
...state,
count: state.count - 1,
};
default:
return state;
}
};
initialState
是我們的初始狀態,計數器初始值為 0。reducer
中,我們使用 switch
語句根據不同的 action.type
來決定如何更新狀態。action.type
是 INCREMENT
,我們就將 count
增加 1;如果是 DECREMENT
,我們就減少 1。action.type
不是我們定義的 action
,reducer
會返回當前的狀態,不做任何改變。最後,來看看如何在 React 中結合 TypeScript 和 Redux 吧!
假設已經配置好 Redux 的 store
,可以使用 useDispatch
和 useSelector
來調用 action
並從狀態中取得數值。
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { increment, decrement } from './actions';
import { CounterState } from './reducers';
function Counter() {
const dispatch = useDispatch();
const count = useSelector((state: CounterState) => state.count);
return (
<div>
<p>當前值: {count}</p>
<button onClick={() => dispatch(increment())}>增加</button>
<button onClick={() => dispatch(decrement())}>減少</button>
</div>
);
}
export default Counter;
useDispatch
用來發送 action
(在這個範例,是發送 increment
和 decrement
)。useSelector
用來從全域狀態中選取需要的 count
值。action
增加或減少。使用 TypeScript 與 Redux,可以讓我們的狀態管理更加健壯,避免錯誤的 action
或狀態更新。